﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Security.Cryptography;
using System.Text;

namespace Domain.Models
{
    public class GitLibaray : BaseEntity
    {
        /// <summary>
        /// Git仓库名
        /// </summary>
        public string Name { get; private set; }
        /// <summary>
        /// 登陆账号
        /// </summary>
        public string Account { get; private set; }
        private string _password;
        /// <summary>
        /// 登陆密码
        /// </summary>
        public string Password
        {
            get { return Decrypt(_password); }
            private set { _password = Encrypt(_password); }
        }
        private readonly string _passwordHash = Guid.NewGuid().ToString().Replace("-", "");
        /// <summary>
        /// 同步间隔/时间（秒）
        /// </summary>
        public int SyncIntervalSecond { get; private set; } = 300;
        /// <summary>
        /// 保存登陆信息
        /// </summary>
        public bool Remember { get; private set; } = true;
        private string _repositoryUrl;
        /// <summary>
        /// Git仓库地址
        /// </summary>
        public Uri RepositoryUrl
        {
            get
            {
                if(Uri.TryCreate(_repositoryUrl,UriKind.Absolute, out Uri result))
                {
                    return result;
                }
                else
                {
                    return default;
                }
            }
            set
            {
                _repositoryUrl = value.AbsoluteUri;
            }
        }
        public string LocalDirectory { get; private set; }
        private readonly List<SyncLog> _logs = new List<SyncLog>();
        /// <summary>
        /// 同步日志
        /// </summary>
        public virtual IReadOnlyCollection<SyncLog> Logs
        {
            get
            {
                return _logs.AsReadOnly();
            }
        }
        private readonly long _createDateTime = 0;
        /// <summary>
        /// 创建时间
        /// </summary>
        public DateTime CreateDateTime => DateTime.UtcNow.AddMilliseconds(_createDateTime);
        private readonly long _modifyDateTime = 0;
        /// <summary>
        /// 修改时间
        /// </summary>
        public DateTime ModifyDateTime => DateTime.UtcNow.AddMilliseconds(_modifyDateTime);

        public GitLibaray(string name, string account)
        {
            Name = name ?? throw new ArgumentNullException(nameof(name));
            Account = account ?? throw new ArgumentNullException(nameof(account));
            if(name.Length > 50) throw new ArgumentOutOfRangeException(nameof(name), name.Length, "名称太长了，最多 50 个字符");
            if (account.Length > 50) throw new ArgumentOutOfRangeException(nameof(account), account.Length, "账号太长了，最多 50 个字符");
        }
        private string Encrypt(string text)
        {
            var bytes = Encoding.UTF8.GetBytes(text);
            var aes = Aes.Create();
            aes.Mode = CipherMode.CBC;
            aes.Padding = PaddingMode.PKCS7;
            aes.Key = Encoding.UTF8.GetBytes(_passwordHash);
            return Convert.ToBase64String(aes.CreateEncryptor().TransformFinalBlock(bytes, 0, bytes.Length));
        }

        private string Decrypt(string text)
        {
            var bytes = Convert.FromBase64String(text);
            var aes = Aes.Create();
            aes.Mode = CipherMode.CBC;
            aes.Padding = PaddingMode.PKCS7;
            aes.Key = Encoding.UTF8.GetBytes(_passwordHash);
            return Encoding.UTF8.GetString(aes.CreateDecryptor().TransformFinalBlock(bytes, 0, bytes.Length));
        }
        /// <summary>
        /// 创建密码
        /// </summary>
        public GitLibaray CreateHashPassword(string password)
        {
            Password = password ?? throw new ArgumentNullException(nameof(password));
            return this;
        }
        /// <summary>
        /// 设置同步/提交时间
        /// </summary>
        /// <param name="interval">时间间隔60-86400（秒）</param>
        public GitLibaray SetSyncIntervalSecond(int interval)
        {
            if (interval > 86400 || interval < 60) throw new ArgumentOutOfRangeException(nameof(interval), interval, "设置不正确，有效的同步时间为 60-86400 ，即1分钟到1天");
            SyncIntervalSecond = interval;

            return this;
        }
        /// <summary>
        /// 保存仓库信息
        /// </summary>
        public GitLibaray RememberMe(bool remember = true)
        {
            Remember = remember;
            return this;
        }
        /// <summary>
        /// 设置Git仓库地址
        /// </summary>
        public GitLibaray SetGitLibraryUrl(string url)
        {
            if (!Uri.TryCreate(url, UriKind.Absolute, out _))
            {
                throw new ArgumentException($"无效的url:{url}", nameof(url));
            }
            _repositoryUrl = url;

            return this;
        }
        /// <summary>
        /// 设置本地仓库位置
        /// </summary>
        public GitLibaray SetLocalDirectory(string path)
        {
            if (!string.IsNullOrEmpty(path)) throw new ArgumentNullException(nameof(path));

            if (!Directory.Exists(path))
            {
                throw new DirectoryNotFoundException($"本地仓库位置无效，{path}");
            }
            LocalDirectory = path;

            return this;
        }
        /// <summary>
        /// 创建同步日志（每次自动同步的时候调用）
        /// </summary>
        public void CreateSyncLog(string message)
        {
            var log = new SyncLog(message ?? throw new ArgumentNullException(nameof(message)));
            _logs.Add(log);
        }
    }
}
